package com.mathlearning.auth.service;

import com.mathlearning.auth.common.BusinessException;
import com.mathlearning.auth.config.OSSConfig;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

/**
 * OSS文件上传服务
 * 
 * 注意：这是简化实现，文件保存到本地
 * 生产环境请使用真实的OSS SDK（阿里云/腾讯云/华为云）
 */
@Service
public class OSSService {

    private static final Logger logger = LoggerFactory.getLogger(OSSService.class);

    @Autowired
    private OSSConfig ossConfig;

    // 允许的图片格式
    private static final List<String> ALLOWED_EXTENSIONS = Arrays.asList("jpg", "jpeg", "png", "gif");
    
    // 文件大小限制：5MB
    private static final long MAX_FILE_SIZE = 5 * 1024 * 1024;

    /**
     * 上传头像
     */
    public String uploadAvatar(MultipartFile file, Long userId) {
        // 1. 验证文件
        validateFile(file);

        // 2. 生成唯一文件名
        String filename = generateFilename(file, userId);

        // 3. 上传文件
        String url = uploadToOSS(file, filename, "avatars");

        logger.info("头像上传成功 - 用户ID: {}, URL: {}", userId, url);

        return url;
    }
    
    /**
     * 通用文件上传（支持视频、封面等）
     * @param file 文件
     * @param subDir 子目录（如 "videos", "covers"）
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file, String subDir) {
        // 1. 检查文件是否为空
        if (file == null || file.isEmpty()) {
            throw new BusinessException("文件不能为空");
        }

        // 2. 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || originalFilename.isEmpty()) {
            throw new BusinessException("文件名不能为空");
        }
        
        String extension = getFileExtension(originalFilename);
        long timestamp = System.currentTimeMillis();
        String filename = String.format("%d_%s.%s", timestamp, 
            java.util.UUID.randomUUID().toString().substring(0, 8), extension);

        // 3. 上传文件
        String url = uploadToOSS(file, filename, subDir);

        logger.info("文件上传成功 - 目录: {}, URL: {}", subDir, url);

        return url;
    }

    /**
     * 验证文件
     */
    private void validateFile(MultipartFile file) {
        // 检查文件是否为空
        if (file == null || file.isEmpty()) {
            throw new BusinessException("文件不能为空");
        }

        // 检查文件大小
        if (file.getSize() > MAX_FILE_SIZE) {
            throw new BusinessException("文件大小超过限制，最大5MB");
        }

        // 检查文件格式
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || originalFilename.isEmpty()) {
            throw new BusinessException("文件名不能为空");
        }

        String extension = getFileExtension(originalFilename);
        if (!ALLOWED_EXTENSIONS.contains(extension.toLowerCase())) {
            throw new BusinessException("不支持的文件格式，仅支持 JPG、PNG、GIF");
        }

        // 检查 MIME 类型
        String contentType = file.getContentType();
        if (contentType == null || !contentType.startsWith("image/")) {
            throw new BusinessException("文件类型错误，请上传图片文件");
        }
    }

    /**
     * 生成文件名
     */
    private String generateFilename(MultipartFile file, Long userId) {
        String extension = getFileExtension(file.getOriginalFilename());
        long timestamp = System.currentTimeMillis();
        return String.format("user_%d_%d.%s", userId, timestamp, extension);
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        int lastDotIndex = filename.lastIndexOf(".");
        if (lastDotIndex > 0 && lastDotIndex < filename.length() - 1) {
            return filename.substring(lastDotIndex + 1);
        }
        return "";
    }

    /**
     * 上传到 OSS
     */
    private String uploadToOSS(MultipartFile file, String filename, String subDir) {
        // 判断是否使用真实 OSS
        boolean useRealOSS = ossConfig.getAccessKeyId() != null 
                && !ossConfig.getAccessKeyId().equals("your-access-key-id")
                && !ossConfig.getAccessKeyId().isEmpty();

        if (useRealOSS) {
            // 生产环境：上传到阿里云OSS
            return uploadToAliyunOSS(file, filename, subDir);
        } else {
            // 开发环境：保存到本地
            return uploadToLocal(file, filename, subDir);
        }
    }

    /**
     * 上传到阿里云 OSS
     */
    private String uploadToAliyunOSS(MultipartFile file, String filename, String subDir) {
        OSS ossClient = null;
        try {
            logger.info("开始上传到阿里云OSS - Endpoint: {}, Bucket: {}", 
                ossConfig.getEndpoint(), ossConfig.getBucketName());
            
            ossClient = new OSSClientBuilder().build(
                ossConfig.getEndpoint(),
                ossConfig.getAccessKeyId(),
                ossConfig.getAccessKeySecret()
            );
            
            String objectName = subDir + "/" + filename;
            ossClient.putObject(ossConfig.getBucketName(), objectName, file.getInputStream());
            
            logger.info("文件上传OSS成功: {}", objectName);
            
            // 返回CDN URL
            if (ossConfig.getCdnUrl() != null && !ossConfig.getCdnUrl().isEmpty()) {
                String cdnUrl = ossConfig.getCdnUrl() + "/" + objectName;
                logger.info("返回CDN URL: {}", cdnUrl);
                return cdnUrl;
            }
            
            // 返回OSS URL
            String ossUrl = String.format("https://%s.%s/%s",
                ossConfig.getBucketName(),
                ossConfig.getEndpoint(),
                objectName
            );
            logger.info("返回OSS URL: {}", ossUrl);
            return ossUrl;
            
        } catch (Exception e) {
            logger.error("OSS上传失败 - Endpoint: {}, Bucket: {}, AccessKeyId: {}", 
                ossConfig.getEndpoint(), 
                ossConfig.getBucketName(),
                ossConfig.getAccessKeyId(), e);
            throw new BusinessException("文件上传失败，请稍后重试: " + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 上传到本地
     */
    private String uploadToLocal(MultipartFile file, String filename, String subDir) {
        try {
            // 创建上传目录
            String uploadDir = "uploads/" + subDir + "/";
            Path uploadPath = Paths.get(uploadDir);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            // 保存文件
            String filepath = uploadDir + filename;
            Path targetPath = Paths.get(filepath);
            Files.copy(file.getInputStream(), targetPath);

            logger.info("文件保存到本地: {}", filepath);

            // 返回访问URL
            return "/uploads/" + subDir + "/" + filename;

        } catch (IOException e) {
            logger.error("本地文件上传失败", e);
            throw new BusinessException("文件上传失败，请稍后重试");
        }
    }

    /**
     * 删除文件（可选）
     */
    public void deleteFile(String filename) {
        try {
            String filepath = "uploads/avatars/" + filename;
            Path path = Paths.get(filepath);
            Files.deleteIfExists(path);
            logger.info("删除文件成功: {}", filename);
        } catch (IOException e) {
            logger.error("删除文件失败: {}", filename, e);
        }
    }
}



